package com.lzx.adx.report.aspect;


import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
@Slf4j
public class BusinessAspect {

    @Pointcut(value = "execution(public *  com.lzx.adx.report.controller..*.*(..))")
    public void pointCut() {

    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            HttpServletRequest httpRequest = getHttpRequest();
            String requestNo = httpRequest.getHeader("requestNo");

            if (StringUtils.isNotBlank(requestNo)) {
                MDC.put("report.requestNo", requestNo);
            } else {
                MDC.put("report.requestNo", UUID.fastUUID().toString());
            }

            MDC.put("report.consumerIp", ServletUtil.getClientIP(httpRequest));

        } catch (Exception e) {
            log.error("接口请求参数统一打印时异常", e);
        }
        return joinPoint.proceed();
    }

    @AfterReturning(returning = "returnObject", pointcut = "pointCut()")
    public void afterExec(JoinPoint joinPoint, Object returnObject) {
        try {
            HttpServletRequest httpRequest = getHttpRequest();
            String uri = httpRequest.getRequestURI();
//            log.info("路径[{}]的响应参数是:[{}]", uri, toHumanStr(returnObject));
        } catch (Exception e) {
            log.error("接口响应参数统一打印时异常", e);
        }
    }

    private HttpServletRequest getHttpRequest() {
        ServletRequestAttributes reqAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = reqAttributes.getRequest();
        return request;
    }


    /**
     * 入参数据
     *
     * @param joinPoint
     * @return
     */
    private String preHandle(ProceedingJoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        if (ArrayUtil.isNotEmpty(args)) {
            StringBuilder sb = new StringBuilder();
            for (Object arg : args) {
                sb.append(toHumanStr(arg)).append(", ");
            }
            sb.delete(sb.length() - 2, sb.length());
            return sb.toString();
        }
        return null;
    }

    /**
     * 转换成可读的字符串
     *
     * @param arg 参数
     */
    private String toHumanStr(Object arg) {
        Object obj = arg;
        String argStr;

        // fastjson无法处理MultipartFile, 将其转换成Map, 下面再转json
        if (arg instanceof MultipartFile) {
            MultipartFile mf = (MultipartFile) arg;
            Map<String, Object> replacement = new HashMap<>(2);
            replacement.put("filename", mf.getName());
            replacement.put("filesize", mf.getSize());
            obj = replacement;
        }
        //处理请求和响应
        if (arg instanceof ServletRequest) {
            obj = ((HttpServletRequest) arg).getParameterMap();
        }

        if (arg instanceof ServletResponse) {
            obj = ((HttpServletResponse) arg).getHeaderNames();
        }

        try {
            argStr = JSON.toJSONString(obj);
        } catch (Exception e) {
            argStr = String.valueOf(obj);
        }
        return argStr;
    }
}
